//--------------------------------------------------------------------------------
// This file is a portion of the D2D1Renderer.  It is distributed
// under the MIT License, available in the root of this distribution and 
// at the following URL:
//
// http://www.opensource.org/licenses/mit-license.php
//
// Copyright (c) Mirco Timmermann
//
//--------------------------------------------------------------------------------
#pragma once
//#include "PCH.h"
#include <d2d1.h>
#include <dwrite.h>

#include <string>
#include <stack>

#include "HTML5CanvasInterfaces\CanvasRenderingContext2D.h"
#include "HTML5CanvasInterfaces\CanvasTransformation.h"
#include "HTML5CanvasInterfaces\CanvasPathMethods.h"
#include "HTML5CanvasInterfaces\CanvasLineStyles.h"

#include "Path.h"
#include "CanvasGradient.h"
#include "LinearGradientBrush.h"


class Image;

//#include "Utils\genericProperty\GenericProperty.h"
//#include "D3D11Engine\display\Stage.h"

//#include "system\base\color\Color.h"

//#include "Utils\makros\Properties.h"


class Direct2DContext : public CanvasRenderingContext2D, CanvasTransformation, CanvasPathMethods, CanvasLineStyles {
	//typedef GenericProperty<std::string, Direct2DContext> Property_str;
public:
	struct Dimension {
		float width;
		float height;
	};

	struct Save {
		D2D1::Matrix3x2F _matrix;
		float _alpha;
	};

public:
	Direct2DContext(ID2D1RenderTarget* renderTarget, ID2D1Factory* d2dFactory, IDWriteFactory* dWriteFactory, IDWriteTextFormat* textFormat);
	~Direct2DContext(void);

	void Resize(int width, int height);

public:
	ID2D1RenderTarget* _renderTarget;

	ID2D1Factory* _d2dFactory;
	IDWriteTextFormat* _textFormat;

	//@DEPRICATED
	//D11::Stage* _stage;

	//@DEPRICATED
	//bool _disableCamera;
	//void SetStage(D11::Stage* stage);

///////////////////////////////////////////////////////////////////////////////////////////////
//                                        PROPERTIES                                         //
///////////////////////////////////////////////////////////////////////////////////////////////

//@DEPRICATED
void SetStrokeStyle(float r, float g, float b);
void SetStrokeStyle(Color r);
void SetStrokeStyle(CanvasGradient canvasGradient);

//@DEPRICATED
void SetFillStyle(float r, float g, float b);
void SetFillStyle(Color color);
void SetFillStyle(CanvasGradient canvasGradient);

// line caps/joins
float lineWidth; // (default 1)

///////////////////////////////////////////////////////////////////////////////////////////////
//                                  DRAW UTILS CREATION                                      //
///////////////////////////////////////////////////////////////////////////////////////////////

private:
	void createD2DBrushes();

private:
	ID2D1SolidColorBrush* _solidColorBrush_stroke;
	ID2D1SolidColorBrush* _solidColorBrush_fill;

	LinearGradientBrush* _linearGradientBrush_fill;
	LinearGradientBrush* _linearGradientBrush_stroke;

	//
	ID2D1Brush* _strokeBrush;
	ID2D1Brush* _fillBrush;


	Path* _path;
	D2D1_RECT_F _rect;

	std::stack<Save> _saveRestoreStack;

///////////////////////////////////////////////////////////////////////////////////////////////
//                                         DRAWS                                             //
///////////////////////////////////////////////////////////////////////////////////////////////

	void draw_strokePath(Path& path);
	void draw_fillPath(Path& path);
	void draw_strokeText(std::string text, float x, float y, float maxWidth);

///////////////////////////////////////////////////////////////////////////////////////////////
//                          DRAW INTERFACE (CanvasRenderingContext2D)                        //
///////////////////////////////////////////////////////////////////////////////////////////////
public:
		virtual void save();
		virtual void restore();
		virtual void clearRect(float x, float y, float w, float h);
		virtual void fillRect(float x, float y, float w, float h);
		virtual void strokeRect(float x, float y, float w, float h);
		virtual void beginPath();
		virtual void fill();
		virtual void stroke();
		virtual void clip();
		virtual void fillText(std::string text, float x, float y, float maxWidth = 0);
		virtual void strokeText(std::string text, float x, float y, float maxWidth = 0);

		virtual CanvasGradient createLinearGradient(float x0, float y0, float x1, float y1);
		virtual CanvasGradient createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1);

///////////////////////////////////////////////////////////////////////////////////////////////
//                                  TRANSFORM INTERFACE                                      //
///////////////////////////////////////////////////////////////////////////////////////////////
public:
		// transformations (default transform is the identity matrix)
		virtual void scale(float x, float y);
		virtual void rotate(float angle);
		virtual void translate(float x, float y);
		virtual void transform(float a, float b, float c, float d, float e, float f);
		virtual void setTransform(float a, float b, float c, float d, float e, float f);

///////////////////////////////////////////////////////////////////////////////////////////////
//                                     PATH INTERFACE                                        //
///////////////////////////////////////////////////////////////////////////////////////////////
public:
		// shared path API methods
		virtual void closePath();
		virtual void moveTo(float x, float y);
		virtual void lineTo(float x, float y);
		virtual void quadraticCurveTo(float cpx, float cpy, float x, float y);
		virtual void bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y);
		virtual void arcTo(float x1, float y1, float x2, float y2, float radius);
		virtual void rect(float x, float y, float w, float h);
		virtual void arc(float x, float y, float radius, float startAngle, float endAngle, bool anticlockwise);

///////////////////////////////////////////////////////////////////////////////////////////////
//                                     IMAGE INTERFACE                                       //
///////////////////////////////////////////////////////////////////////////////////////////////
public:
		/*
		* sx = Optional. The x coordinate where to start clipping
		* sy = Optional. The y coordinate where to start clipping
		* sw = Optional. The width of the clipped image
		* sh = Optional. The height of the clipped image
		* dx = The x coordinate where to place the image on the canvas
		* dy = The y coordinate where to place the image on the canvas
		* dw = The width of the image
		* dh = The height of the image
		*/
		virtual void drawImage(Image* image, int dx, int dy);
		virtual void drawImage(Image* image, int dx, int dy, int dw, int dh);
		virtual void drawImage(Image* image, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh);

///////////////////////////////////////////////////////////////////////////////////////////////
//                                         EXTENTION                                         //
///////////////////////////////////////////////////////////////////////////////////////////////

private:
	IDWriteFactory* _dWriteFactory;

public:
	Dimension measureText(std::string text);

};